package jp.dodododo.dao.dialect;

import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;

import javax.sql.DataSource;

import jp.dodododo.dao.message.Message;
import jp.dodododo.dao.util.ClassUtil;
import jp.dodododo.dao.util.ConnectionUtil;
import jp.dodododo.dao.util.DataSourceUtil;
import jp.dodododo.dao.util.DatabaseMetaDataUtil;
import jp.dodododo.dao.util.PropertiesUtil;

public abstract class DialectManager {

	private static Properties dialectClassNames = PropertiesUtil.getProperties("jp/dodododo/dao/dialect.properties");

	private static Map<String, Dialect> dialectInstances = Collections.synchronizedMap(new HashMap<String, Dialect>());

	public static Dialect getDialect(DataSource dataSource) {
		Connection connection = null;
		try {
			connection = DataSourceUtil.getConnection(dataSource);
			return getDialect(connection);
		} finally {
			ConnectionUtil.close(connection);
		}
	}

	public static Dialect getDialect(Connection connection) {
		DatabaseMetaData dmd = ConnectionUtil.getMetaData(connection);
		return getDialect(dmd);
	}

	public static Dialect getDialect(DatabaseMetaData dmd) {
		return getDialect(DatabaseMetaDataUtil.getDatabaseProductName(dmd));
	}

	public static Dialect getDialect(String productName) {
		Dialect dialect = dialectInstances.get(productName);
		if (dialect != null) {
			return dialect;
		}
		String className = dialectClassNames.getProperty(productName);
		if (className == null) {
			throw new UnsupportedOperationException(Message.getMessage("00014", productName));
		}

		Class<? extends Dialect> clazz = ClassUtil.forName(className);
		dialect = ClassUtil.newInstance(clazz);
		dialectInstances.put(productName, dialect);
		return dialect;
	}

	public static void addDialect(String productName, Dialect dialect) {
		dialectInstances.put(productName, dialect);
	}
}
